class AtomicInt {
public:
    AtomicInt() = default;

    explicit AtomicInt(int value) : value(value) {}

    virtual ~AtomicInt() {
        pthread_mutex_destroy(&_mutex);
    }

private:
    int value = 0;

    pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;

public:
    int getValue() const {
        return value;
    }

    pthread_mutex_t getMutex() {
        return _mutex;
    }

public:
    int operator()() const {
        return value;
    }

    AtomicInt &operator++() {
        pthread_mutex_lock(&_mutex);
        value++;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator++(int) {
        pthread_mutex_lock(&_mutex);
        value++;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator--() {
        pthread_mutex_lock(&_mutex);
        value--;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator--(int) {
        pthread_mutex_lock(&_mutex);
        value--;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator+(int _add) {
        pthread_mutex_lock(&_mutex);
        value += _add;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator+=(int _add) {
        pthread_mutex_lock(&_mutex);
        value += _add;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator-(int _del) {
        pthread_mutex_lock(&_mutex);
        value -= _del;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator-=(int _del) {
        pthread_mutex_lock(&_mutex);
        value -= _del;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator*(int _mul) {
        pthread_mutex_lock(&_mutex);
        value *= _mul;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator*=(int _mul) {
        pthread_mutex_lock(&_mutex);
        value *= _mul;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator/(int _div) {
        pthread_mutex_lock(&_mutex);
        value /= _div;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator/=(int _div) {
        pthread_mutex_lock(&_mutex);
        value /= _div;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator=(int _int) {
        this->value = _int;
        return *this;
    }

    AtomicInt &operator=(AtomicInt _int) {
        this->value = _int.value;
        return *this;
    }

    AtomicInt &operator+(AtomicInt _int) {
        pthread_mutex_lock(&_mutex);
        value += _int.value;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator+=(AtomicInt _int) {
        pthread_mutex_lock(&_mutex);
        value += _int.value;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator-(AtomicInt _int) {
        pthread_mutex_lock(&_mutex);
        value -= _int.value;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator-=(AtomicInt _int) {
        pthread_mutex_lock(&_mutex);
        value -= _int.value;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator*(AtomicInt _int) {
        pthread_mutex_lock(&_mutex);
        value *= _int.value;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator*=(AtomicInt _int) {
        pthread_mutex_lock(&_mutex);
        value *= _int.value;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator/(AtomicInt _int) {
        pthread_mutex_lock(&_mutex);
        value /= _int.value;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }

    AtomicInt &operator/=(AtomicInt _int) {
        pthread_mutex_lock(&_mutex);
        value /= _int.value;
        pthread_mutex_unlock(&_mutex);
        return *this;
    }
};